前言:多线程I/O中的“优雅失败”信号在JavaNIO的并发编程模型中,AsynchronousCloseException是一个极其特殊且常被误解的异常。 本文将基于JDK源码与NIO规范,对AsynchronousCloseException进行原子级解构。 AsynchronousCloseException→检查并发协调,关闭是否是预期的?是否需要通知其他组件? Java的共享可变状态模型使得AsynchronousCloseException成为必要。 ,I/O线程能正确响应AsynchronousCloseException并退出确认日志级别:AsynchronousCloseException应为DEBUG/INFO,而非ERROR评估是否可以通过所有权设计
* * Any thread currently blocked in an I/O operation upon this channel * will receive an AsynchronousCloseException 仅设置中断处理标志 interrupt0(); } end 方法: protected final void end(boolean completed) throws AsynchronousCloseException open){ //当前线程发现Channel被关闭了,并且是读取还未执行完毕的情况,则抛出AsynchronousCloseException异常,表示Channel被异步关闭了。 throw new AsynchronousCloseException(); } 如果手动实现一个可中断的channel时,手动处理中断应该是: this.outstream = Channels.newChannel (outstream); try { outstream.write(message); } catch(AsynchronousCloseException e) { System.out.println
3.图中第@6:标记I/O结束操作end()源码 protected final void end(boolean completed) throws AsynchronousCloseException null; throw new ClosedByInterruptException(); } // I/O操作未完成而Channel通道被别的线程关闭 // 抛出AsynchronousCloseException open) throw new AsynchronousCloseException(); } 小结:end()操作标记I/O的结束,与begin()操作结对出现;根据不同的中断场景抛出不同的异常
参数:remote-与此通道连接的远程地址 返回:此数据报通道 抛出: ClosedChannelException-如果此通道已关闭 AsynchronousCloseException-如果正在进行连接操作时另一个线程关闭了此通道 要向其中传输数据报的缓冲区 返回:数据报的源地址,或者如果此通道处于非阻塞模式并且没有直接可用的数据报,则返回null 抛出: ClosedChannelException-如果此通道已关闭 AsynchronousCloseException 可能是调用此方法时源缓冲区中剩余的字节数,或者如果此通道处于非阻塞模式并且基础输出缓冲区中没有足够的空间供数据报使用,则可能为零 抛出: ClosedChannelException-如果此通道已关闭 AsynchronousCloseException 可能为零,如果该通道已到达流的末尾,则返回-1 抛出: NotYetConnectedException-如果未连接此通道的套接字 ClosedChannelException-如果此通道已关闭 AsynchronousCloseException 要从中检索字节的缓冲区 返回:写入的字节数,可能为零 抛出: NotYetConnectedException-如果未连接此通道的套接字 ClosedChannelException-如果此通道已关闭 AsynchronousCloseException
(NIO1.0)AsynchronousChannel(NIO.2)close()行为立即中断阻塞线程,抛ClosedByInterruptException异步通知所有outstanding操作,抛AsynchronousCloseException throwsIOException;AsynchronousChannel.close()的行为远比同步Channel.close()复杂:阶段行为异常类型Outstanding操作异步完成(非立即中断)AsynchronousCloseException )←t0的操作收到此异常t3:channel.read(buf2,handler2)←新操作t4:handler2.failed(ClosedChannelException)←t3的操作收到此异常AsynchronousCloseException 所有其他outstanding操作收到AsynchronousCloseException。通道进入关闭状态,后续操作全部失败。这是一个破坏性操作,不应作为常规的流控手段。 常见陷阱清单陷阱后果解决方案在handler中捕获外部可变状态数据竞争/内存泄漏使用attachment传递上下文cancel(true)后继续I/O未指定运行时异常仅用cancel(false),或关闭后重建通道忽略AsynchronousCloseException
implements Channel, InterruptibleChannel { protected final void end(boolean completed) throws AsynchronousCloseException open) throw new AsynchronousCloseException(); } ...... } Interrupt 关闭 Channel 实例
catch (SocketTimeoutException ignored) { // wake up to see if should continue to run } catch (AsynchronousCloseException
通道提供一套统一的、高效的解决方案,以实现以下目标:异步关闭(AsynchronousClose)当一个线程调用channel.close()时,任何其他正在该通道上执行阻塞I/O操作的线程都应立即被唤醒,并抛出AsynchronousCloseException 只有当操作未完成且通道已关闭时,才抛出AsynchronousCloseException。
} catch (IOException e) { // ClosedChannelException // AsynchronousCloseException throw new IOException("Error happened when receiving packet."); } } catch (AsynchronousCloseException
则读阻塞的线程将返回-1 表示没有 读取任何数据;如果 SocketChannel 在一个线程上 write 阻塞,另一个线程对该 SocketChannel 调用 shutdownWrite,则写阻塞的线程将抛出AsynchronousCloseException
则读阻塞的线程将返回-1 表示没有 读取任何数据;如果SocketChannel 在一个线程上 write 阻塞,另一个线程对该 SocketChannel 调用shutdownWrite,则写阻塞的线程将抛出 AsynchronousCloseException
ShutdownChannelGroupException异步异常I/O完成时handler.failed()或Future.get()IOException,ClosedChannelException,AsynchronousCloseException6.2ShutdownChannelGroupException
如果不允许从此通道进行读取操作 NonWritableChannelException - 如果目标通道不允许进行写入操作 ClosedChannelException - 如果此通道或目标通道已关闭 AsynchronousCloseException
当关闭一个 InterruptibleChannel 时,将导致所有在链路操作上阻塞的线程抛出 AsynchronousCloseException。
当关闭一个InterruptibleChannel时,将导致所有在链路操作上阻塞的线程都抛出AsynchronousCloseException。
ClosedChannelException * If either this channel or the target channel is closed * * @throws AsynchronousCloseException
当一个通道被关闭时,休眠在该通道上的所有线程都将被唤醒并接收到一个 AsynchronousCloseException 异常。接着通道就被关闭并将不再可用。 如果通道被另外一个线程关闭,该暂停线程将恢复并产生一个AsynchronousCloseException 异常。
AsynchronousChannel.class classes/java/nio/channels/AsynchronousChannelGroup.class classes/java/nio/channels/AsynchronousCloseException.class